#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <pthread.h>
#include <unistd.h>

// 线程信息结构体：存储线程 ID 和名称
struct ThreadInfo
{
    pthread_t tid;      // 线程 ID
    std::string name;   // 线程名称（用于调试）
};

static const int defaultnum = 5;  // 默认线程池线程数

template <class T>
class ThreadPool
{
public:
    // 加锁（封装 pthread_mutex_lock）
    void Lock()
    {
        pthread_mutex_lock(&_mutex);
    }

    // 解锁（封装 pthread_mutex_unlock）
    void Unlock()
    {
        pthread_mutex_unlock(&_mutex);
    }

    // 唤醒一个等待的线程（封装 pthread_cond_signal）
    void WakeUp()
    {
        pthread_cond_signal(&_cond);
    }

    // 让当前线程休眠（封装 pthread_cond_wait）
    void ThreadSleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }

    // 判断任务队列是否为空
    bool IsQueueEmpty()
    {
        return _tasks.empty();
    }

    // 根据线程 ID 获取线程名称
    std::string GetThreadName(pthread_t tid)
    {
        for (const auto &ti : _threads)
        {
            if (ti.tid == tid)
                return ti.name;
        }
        return "None";
    }

public:
    // 线程函数（静态方法，因为 pthread_create 需要 C 风格的函数指针）
    static void *HandlerTask(void *args)
    {
        ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);  // 获取线程池对象
        std::string name = tp->GetThreadName(pthread_self());    // 获取当前线程名称

        while (true)
        {
            tp->Lock();  // 加锁

            // 如果任务队列为空，线程休眠（避免忙等待）
            while (tp->IsQueueEmpty())
            {
                tp->ThreadSleep();
            }

            // 从任务队列取出一个任务
            T t = tp->Pop();
            tp->Unlock();  // 解锁

            t();  // 执行任务（T 必须是可调用对象，如函数对象、lambda）
        }
    }

    // 启动线程池（创建所有线程）
    void Start()
    {
        int num = _threads.size();
        for (int i = 0; i < num; i++)
        {
            _threads[i].name = "thread-" + std::to_string(i + 1);  // 设置线程名称
            pthread_create(&(_threads[i].tid), nullptr, HandlerTask, this);  // 创建线程
        }
    }

    // 从任务队列取出一个任务
    T Pop()
    {
        T t = _tasks.front();
        _tasks.pop();
        return t;
    }

    // 向任务队列添加任务
    void Push(const T &t)
    {
        Lock();      // 加锁
        _tasks.push(t);  // 添加任务
        WakeUp();    // 唤醒一个线程
        Unlock();    // 解锁
    }

    // 获取线程池单例（线程安全）
    static ThreadPool<T> *GetInstance()
    {
        if (nullptr == _tp)  // 第一次检查（避免每次加锁）
        {
            pthread_mutex_lock(&_lock);  // 加锁
            if (_tp == nullptr)         // 第二次检查（防止多线程竞争）
            {
                std::cout << "log: singleton create done first! " << std::endl;
                _tp = new ThreadPool<T>();  // 创建单例
            }
            pthread_mutex_unlock(&_lock);  // 解锁
        }
        return _tp;
    }

private:
    // 构造函数（私有，确保只能通过 GetInstance 创建）
    ThreadPool(int num = defaultnum)
        : _threads(num)  // 初始化线程数组
    {
        pthread_mutex_init(&_mutex, nullptr);  // 初始化互斥锁
        pthread_cond_init(&_cond, nullptr);    // 初始化条件变量
    }

    // 析构函数（清理资源）
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);  // 销毁互斥锁
        pthread_cond_destroy(&_cond);    // 销毁条件变量
    }

    // 禁用拷贝构造和赋值（单例模式）
    ThreadPool(const ThreadPool<T> &a) = delete;
    const ThreadPool<T> &operator=(const ThreadPool<T> &a) = delete;

private:
    std::vector<ThreadInfo> _threads;  // 线程数组（存储线程信息）
    std::queue<T> _tasks;              // 任务队列（存储待执行的任务）

    pthread_mutex_t _mutex;  // 互斥锁（保护任务队列）
    pthread_cond_t _cond;    // 条件变量（线程同步）

    static ThreadPool<T> *_tp;      // 单例对象指针
    static pthread_mutex_t _lock;   // 单例锁（保证 GetInstance 线程安全）
};

// 静态成员初始化
template <class T>
ThreadPool<T> *ThreadPool<T>::_tp = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::_lock = PTHREAD_MUTEX_INITIALIZER;  // 静态锁初始化